package futbol.tacticas.concursantes.Tactica_Decano_Tricolor;

import java.awt.Color;
import java.awt.Point;
import java.util.Vector;

import futbol.tacticas.Comando;
import futbol.tacticas.ComandoGolpearBola;
import futbol.tacticas.ComandoIrA;
import futbol.tacticas.ComandoTiroAPuerta;
import futbol.tacticas.SituacionJugadores;
import futbol.tacticas.concursantes.Tactica;

/**
 *
 * @author Daniel
 */
public class Tactica_Decano_Tricolor implements Tactica {

    long marcador,marcaMiCampo,marcaSuCampo;
    long subMarcador=1;
    int golesMios,golesSuyos;
    long contadorBolaParada;
    
    boolean estadoCritico=false;
    boolean annul=false;
    double[] velocidadContrarios = new double[11];
    Point[] posicionContrarios = new Point[11];
    Point posicionBola = new Point(0,0);
    
    int[] asignaciones = new int[11];
    int inicioC=1; 
    int finC = 10; 
    int lejano1,lejano2;

    
    private int nValores[][]={
        {-155,0,6}, 
        {-90,100,5}, {-110,30,5}, {70,0,6},      
        {-100,-100,6}, {60,100,6}, {-30,30,6}, {-10,-30,7},
        {30,-100,7}, {120,30,7}, {70,0,7} 
    };

    public String getNombre(){
        return "Decano Tricolor";
    }
    
    public Color getColor1(){
        return Color.blue;
    }
    
    public Color getColor2(){
        return Color.white;
    }
    
    public Color getColorNumero(){
        return Color.red;
    }
    
    public int getFuerza(int n){
        return nValores[n][2];
    }
    public int getXInicial(int n){
        return nValores[n][0];
    }
    
    public int getYInicial(int n){
        return nValores[n][1];
    }
    
    public Vector<Comando> getComandos(SituacionJugadores sj){


    	Point posBola=sj.getBola();
    	Vector <Comando> comandos=new Vector<Comando> ();

    	comandos.add(new ComandoIrA(10, nValores[10][0], nValores[10][1]));
    	if (normaDos( posBola.getX()-sj.getMisJugadores()[10].getX() , posBola.getY()-sj.getMisJugadores()[10].getY() )<40)
    		movimientoJugadorOptimo(10,sj,comandos);
    	comandos.add(new ComandoTiroAPuerta(10,0)); 

    	medicionContrarios(sj);

    	if (chequeaAlarmaPortero(sj)==true) movimientoJugadorOptimo(0,sj,comandos);
    	else 
    		muevePorteroSinAlarma(sj,comandos);

    	comandos.add(new ComandoGolpearBola(0,100,0)); 




    	asignaCubribles(sj);
    	cubreTodos(sj,comandos);





    	if ((marcador>=800)&&(golesMios==0)) annul=true;

    	if (posBola.getX()<0) marcaMiCampo++; else marcaSuCampo++;

    	if ((posBola.getX()>=160)&&(Math.abs(posBola.getY())<30)) {golesMios++; subMarcador=0;}
    	if  ((posBola.getX()<=-160)&&(Math.abs(posBola.getY())<30)) {golesSuyos++; subMarcador=0;}


    	if ( (posBola.getX()==posicionBola.getX()) && (posBola.getY()==posicionBola.getY()) ) 
    		contadorBolaParada++;
    	else contadorBolaParada=0;

    	if (contadorBolaParada>90){
    		if ((golesSuyos>golesMios+1) || 
    				((golesSuyos==golesMios)&&(posBola.getX()<=0)&&(1800-marcador>=marcaSuCampo-marcaMiCampo)) || 
    				((golesSuyos==golesMios)&&(posBola.getX()>0)&&(1800-marcador<=marcaMiCampo-marcaSuCampo)) ) 

    			comandos.add(new ComandoIrA(10,posBola.getX(),posBola.getY()));
    	}

    	marcador++;
    	subMarcador++;
    	updatePosicionBola(sj);
    	return comandos;
    }

    public double normaDos(double x,double y){
    	return Math.sqrt(Math.pow(x,2)+Math.pow(y,2));

    }

    public double dameDistContrMasCercano(double x, double y,SituacionJugadores sj){
    	int n= sj.getContrarioMasCerca(x,y);
    	return normaDos(x-sj.getContrario()[n].getX(),y-sj.getContrario()[n].getY());
    }

    public void medicionContrarios(SituacionJugadores sj){
    	if (marcador==1) {
    		posicionContrarios=sj.getContrario();
    	}
    	if (marcador==2) {
    		for (int i=0;i<11;i++){
    			velocidadContrarios[i] = Math.round( normaDos( posicionContrarios[i].getX()-sj.getContrario()[i].getX() , posicionContrarios[i].getY()-sj.getContrario()[i].getY() ) );
    			if ((velocidadContrarios[i]<3)||(velocidadContrarios[i]>6)) velocidadContrarios[i]=7;
    		}
    	}
    }



    public int dameAmigoMasCercano(int n,SituacionJugadores sj){
    	int pivote = 0;
    	double pivote2 = 1000;
    	Point[] misJugadores=sj.getMisJugadores() ;
    	for (int i=1;(i<11);i++){
    		if ((i!=n)&&(pivote2 > normaDos ( misJugadores[i].getX()-misJugadores[n].getX() , misJugadores[i].getY()-misJugadores[n].getY() ))){
    			pivote2 = normaDos ( misJugadores[i].getX()-misJugadores[n].getX() , misJugadores[i].getY()-misJugadores[n].getY() ); pivote=i;}
    	}
    	return pivote;

    }


    public void movimientoJugadorOptimo(int nJug, SituacionJugadores sj, Vector<Comando> com){

    	double p2x = sj.getMisJugadores()[nJug].getX();
    	double p2y = sj.getMisJugadores()[nJug].getY();
    	double p1x = sj.getBola().getX();
    	double p1y = sj.getBola().getY();
    	double vx = getVelocidadBolaX(sj);
    	double vy = getVelocidadBolaY(sj);
    	double x = dameProyeccionX(p1x,p1y,p2x,p2y,vx,vy);
    	double y = dameProyeccionY(p1x,p1y,p2x,p2y,vx,vy);
    	double v = normaDos(getVelocidadBolaX(sj),getVelocidadBolaY(sj));
    	double r = (v+1)*v/2;
    	double t = normaDos(x-p1x,y-p1y);
    	if (r<t) com.add(new ComandoIrA( nJug , (int)p1x+vx*(r-1)/v , (int)p1y+vy*(r-1)/v )); 
    	else com.add(new ComandoIrA(nJug,(int)x,(int)y));    
    }



    public double dameProyeccionX(double p1x, double p1y, double p2x, double p2y, double vx, double vy){
    	double r;
    	if ((vx==0)&&(vy==0)) r=0;
    	else r = -(p1x*vx-p2x*vx+p1y*vy-p2y*vy)/(Math.pow(vx,2)+Math.pow(vy,2));
    	return (p1x+r*vx);
    }

    public double dameProyeccionY(double p1x, double p1y, double p2x, double p2y, double vx, double vy){
    	double r;
    	if ((vx==0)&&(vy==0)) r=0;
    	else r = -(p1x*vx-p2x*vx+p1y*vy-p2y*vy)/(Math.pow(vx,2)+Math.pow(vy,2));
    	return (p1y+r*vy);  
    }

    public double getVelocidadBolaX(SituacionJugadores sj){
    	return sj.getBola().getX()-posicionBola.getX();
    }


    public double getVelocidadBolaY(SituacionJugadores sj){
    	return sj.getBola().getY()-posicionBola.getY();
    }


    public void updatePosicionBola(SituacionJugadores sj){
    	if (Math.abs(sj.getBola().getX())>=158) posicionBola=new Point(0,0);
    	else;
    	posicionBola=sj.getBola();
    }

    public  boolean chequeaAlarmaPortero(SituacionJugadores sj){


    	double choque = sj.getBola().getY()+getVelocidadBolaY(sj)*
    	((-160-sj.getBola().getX())/getVelocidadBolaX(sj) );

    	boolean a = ((Math.abs( choque ) < 32)&&(getVelocidadBolaX(sj)<0));

    	double d = normaDos ((sj.getBola().getX()+160)/(2.5),sj.getBola().getY());
    	boolean b = d<70;
    	return (a && b);
    }


    public void muevePorteroSinAlarma(SituacionJugadores sj,Vector<Comando> com){
    	double signo = sj.getBola().getY()/Math.abs(sj.getBola().getY());
    	if (sj.getBola().getY()==0) signo=1;
    	double x=dameProyeccionX( sj.getBola().getX() , sj.getBola().getY() , -155 , 35*signo , -160-sj.getBola().getX() , -sj.getBola().getY() );
    	double y=dameProyeccionY( sj.getBola().getX() , sj.getBola().getY() , -155 , 35*signo , -160-sj.getBola().getX() , -sj.getBola().getY() );
    	com.add(new ComandoIrA(0,(int)x,(int)y)); 
    }





    public void asignaCubribles(SituacionJugadores sj){

    	Point[] contrarios = sj.getContrario();
    	Point[] propios = sj.getMisJugadores();

    	if (subMarcador==1){

    		//System.out.println("cucu");

    		for (int i=0;i<11;i++) asignaciones[i]=i;

    		double pivote;
    		int[] contrariosAsignados = new int[11];
    		int pivoteP=0;
    		int pivoteP2=0;
    		int[] propiosAsignados = new int [11];
    		double dist,dist2;

    		for (int i=0;i<finC-inicioC;i++){  //de entre todos los contrarios
    			pivote=500;
    			for (int k=0;k<11;k++){  //buscamos el (i+1)�simo m�s lejano resp porter�a, finC-inicioC veces, que ser� el n�mero pivoteP
    				dist2=normaDos(contrarios[k].getX()+160,contrarios[k].getY());
    				if ((dist2<pivote)&&( contrariosAsignados[k]!=1 )) { pivote=dist2; pivoteP=k; }
    			}
    			contrariosAsignados[pivoteP]=1;

    			dist=500;
    			for (int j=inicioC; j<finC;j++){ //para �l buscamos el propio m�s cercano que no est� asignado
    				if  ((normaDos(contrarios[pivoteP].getX()-propios[j].getX(),contrarios[pivoteP].getY()-propios[j].getY())<dist) && ( propiosAsignados[j]!=1 )){
    					dist=normaDos(contrarios[pivoteP].getX()-propios[j].getX(),contrarios[pivoteP].getY()-propios[j].getY()); 
    					pivoteP2=j; 
    				}
    			}
    			asignaciones[pivoteP2]=pivoteP;
    			propiosAsignados[pivoteP2]=1;          
    		}

    		for(int f=0; f<11; f++) if (contrariosAsignados[f]==0) lejano1=f;
    		for(int f=0; f<11; f++) if ((contrariosAsignados[f]==0)&&(f!=lejano1)) lejano2=f;

    	} else {



    		double pivote;
    		int[] contrariosAsignados= new int[11];
    		int pivoteP=0;
    		double dist;

    		for (int i=0; i<10; i++){ //vuelve a ordenar de cercano a lejano

    			pivote=500;
    			for (int j=0; j<11; j++){
    				dist=normaDos(contrarios[j].getX()+160,contrarios[j].getY());
    				if ((dist<pivote)&&(contrariosAsignados[j]!=1)) {pivoteP=j; pivote=dist;}
    			}
    			contrariosAsignados[pivoteP]=1;

    			if ( (i<9) && ((pivoteP==lejano1)||(pivoteP==lejano2)) ) {subMarcador=0; //System.out.println("reseteado");
    			}

    		} 

    	}

    	return;
    }






    public void cobertura(int nJug, int nCon, SituacionJugadores sj, Vector<Comando> com){

    	double x = sj.getBola().getX() - sj.getContrario()[nCon].getX();
    	double y = sj.getBola().getY() - sj.getContrario()[nCon].getY();
    	double n = normaDos(x,y);
    	double nx = sj.getContrario()[nCon].getX()+(x/n)*20;
    	double ny = sj.getContrario()[nCon].getY()+(y/n)*20;
    	com.add(new ComandoIrA(nJug,(int)nx,(int)ny)); 

  
    	double lx,ly;
    	if (annul==false){
    		lx = sj.getMisJugadores()[10].getX()-sj.getBola().getX();
    		ly = sj.getMisJugadores()[10].getY()-sj.getBola().getY();
    	} else {
    		double pivote=0;
    		int pivoteP=0;
    		int nJ=0;
    		double d;
    		for (int i=0;i<27;i++) {
    			nJ=sj.getContrarioMasCerca(160,Math.pow(-1,i)*i);
    			d=normaDos( sj.getContrario()[nJ].getX()-160 , sj.getContrario()[nJ].getY()-Math.pow(-1,i)*i );
    			if ( d>pivote ) {
    				pivote=d;
    				pivoteP=i;
    			}
    		}
    		lx = 160-sj.getBola().getX();
    		ly = Math.pow(-1,pivoteP)*pivoteP-sj.getBola().getY();
    		
    	}

    	if ((lx*x+ly*y)<0) 
    		if ((lx*y-ly*x)>0) 
    		{lx=y;
    		ly=-x;}
    		else{lx=-y;
    		ly=x;}
    	com.add(new ComandoGolpearBola( nJug , sj.getBola().getX()+lx*100 , sj.getBola().getY()+ly*100 ));
   


    }



    public void cubreTodos(SituacionJugadores sj, Vector<Comando> com){

    	for (int i=inicioC;i<finC;i++){
    		cobertura(i,asignaciones[i],sj,com);   
    	}
    	return;
    }
}
